﻿using Fuse8.ContentManagementFramework.Administration.Models;
using Fuse8.ContentManagementFramework.Administration.Models.MetaFields;
using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.ContentManagementFramework.SystemFacade;
using Fuse8.ContentManagementFramework.SystemFacade.Extensions;
using Fuse8.DomainFramework.BusinessService;
using Fuse8.DomainFramework.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace Fuse8.ContentManagementFramework.Administration.Controllers
{
    [ValidateInput(false)]
    public abstract class CmsBaseEntityMetaFieldLinkController : CmsAdminController
    {
        protected virtual string IndexActionName
        {
            get { return "index"; }
        }

        protected virtual string IndexUrl
        {
            get { return null; }
        }

        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Add()
        {
            var model = new CmsEntityMetaFieldLinkModel
                            {
                                EntityTypeParameter = TypeParameter,
                                Values = new List<CmsKeyValueItem>() { new CmsKeyValueItem() },
                                ValuesProviders = MetaValuesProviderManager.Providers.Select(p => p.Name)
                            };

            ViewBag.IndexUrl = this.IndexUrl;
            return View(model);
        }

        protected abstract string TypeParameter { get; }

        [HttpPost]
        public ActionResult Add(CmsEntityMetaFieldLinkModel model, [ModelBinder(typeof(EntityMetaLinkValuesBinder))]string valueSettings)
        {
            Validate(model);
            if (ModelState.IsValid)
            {
                ProcessModel(model, new CmsEntityMetaFieldLink() { EntityMetaField = new CmsEntityMetaField() }, valueSettings);
                return SuccessRedirect();
            }

            if (valueSettings != null)
            {
                try
                {
                    var provider = MetaValuesProviderManager.Provider(model.MetaValuesProviderName);
                    if (provider != null)
                    {
                        provider.SetSettings(ViewData, valueSettings);
                        model.ValuesControl = provider.AdministrationViewName;
                    }
                }
                catch
                {
                }
            }

            model.ValuesProviders = MetaValuesProviderManager.Providers.Select(p => p.Name);

            ViewBag.IndexUrl = this.IndexUrl;
            return View(model);
        }

        private ActionResult SuccessRedirect()
        {
            if (IndexUrl != null)
            {
                return Redirect(IndexUrl);
            }
            return RedirectToAction(IndexActionName);
        }

        private void Validate(CmsEntityMetaFieldLinkModel model)
        {
            var data = new CmsEntityMetaFieldLinkService().FindForEntityType(model.EntityTypeParameter);
            if (data.Any(p => p.EntityMetaField.MetaFieldName == model.MetaFieldName && model.EntityMetaFieldId != p.EntityMetaFieldId))
            {
                ModelState.AddModelError("MetaFieldName", "Meta field with this name already exists");
            }
            if (model.PredefinedListOfValues && string.IsNullOrEmpty(model.MetaValuesProviderName))
            {
                ModelState.AddModelError("MetaValuesProviderName", "Please select an option");
            }
        }

        private void ProcessModel(CmsEntityMetaFieldLinkModel model, CmsEntityMetaFieldLink entity, string valueSettings)
        {
            entity.DisplayLabel = model.DisplayLabel;
            entity.EntityMetaField.MetaFieldName = model.MetaFieldName;
            entity.EntityMetaField.MetaFieldType = TypeInterpreter.GetTypeName(Type.GetType(model.MetaFieldType));
            entity.EntityMetaField.IsSystem = model.IsSystem;
            entity.EntityMetaField.MetaFieldDescription = model.MetaFieldDescription;
            entity.EntityMetaFieldId = model.EntityMetaFieldId;
            entity.EntityTypeParameter = model.EntityTypeParameter;
            entity.IsAllowMultipleValues = model.IsAllowMultipleValues;
            entity.EditorName = model.EditorName;
            entity.DefaultValue = model.DefaultValue;
            entity.IsRequired = model.IsRequired;

            if (!string.IsNullOrEmpty(model.MetaValuesProviderName))
            {
                var value = new CmsEntityMetaFieldLinkValue()
                                {
                                    ProviderName = model.MetaValuesProviderName,
                                    Settings = valueSettings,
                                    AddPleaseSelect = model.AddPleaseSelect
                                };
                entity.MetaFieldValues = value.StoreMe();
            }
            else
            {
                entity.MetaFieldValues = "";
            }

            if (entity.IsNew)
            {
                new BusinessServiceFacade<CmsEntityMetaFieldLink, int>().Add(entity);
            }
            else
            {
                new BusinessServiceFacade<CmsEntityMetaFieldLink, int>().Save(entity);
            }
        }

        [HttpGet]
        public ActionResult Edit(int id)
        {
            var model = new CmsEntityMetaFieldLinkModel();
            var entity = new BusinessServiceFacade<CmsEntityMetaFieldLink, int>().FindOne(id);
            model.DisplayLabel = entity.DisplayLabel;
            model.MetaFieldName = entity.EntityMetaField.MetaFieldName;
            model.MetaFieldType = entity.EntityMetaField.MetaFieldType;
            model.IsSystem = entity.EntityMetaField.IsSystem;
            model.MetaFieldDescription = entity.EntityMetaField.MetaFieldDescription;
            model.EntityMetaFieldId = entity.EntityMetaFieldId;
            model.EntityTypeParameter = entity.EntityTypeParameter;
            model.IsAllowMultipleValues = entity.IsAllowMultipleValues;
            model.IsRequired = entity.IsRequired;
            model.DefaultValue = entity.DefaultValue;
            model.EditorName = entity.EditorName;
            model.Id = entity.Id;
            model.PredefinedListOfValues = false;
            model.ValuesProviders = MetaValuesProviderManager.Providers.Select(p => p.Name);
            try
            {
                var value = entity.MetaFieldValues.DigUpFromString<CmsEntityMetaFieldLinkValue>();
                model.MetaValuesProviderName = value.ProviderName;
                model.AddPleaseSelect = value.AddPleaseSelect;
                var provider = MetaValuesProviderManager.Provider(value.ProviderName);
                if (provider != null)
                {
                    provider.SetSettings(ViewData, value.Settings);
                    model.PredefinedListOfValues = true;
                    model.ValuesControl = provider.AdministrationViewName;
                }
            }
            catch
            {
            }

            ViewBag.IndexUrl = this.IndexUrl;
            return View(model);
        }

        [HttpPost]
        public ActionResult Edit(CmsEntityMetaFieldLinkModel model, [ModelBinder(typeof(EntityMetaLinkValuesBinder))]string valueSettings)
        {
            Validate(model);
            if (ModelState.IsValid)
            {
                ProcessModel(model, new BusinessServiceFacade<CmsEntityMetaFieldLink, int>().FindOne(model.Id), valueSettings);
                return SuccessRedirect();
            }

            ViewBag.IndexUrl = this.IndexUrl;
            return View(model);
        }

        public ActionResult GetAddtionalViewForm(string name)
        {
            var provider = MetaValuesProviderManager.Provider(name);

            if (provider != null && !string.IsNullOrEmpty(provider.AdministrationViewName))
            {
                provider.SetSettings(ViewData, null);

                return PartialView(provider.AdministrationViewName);
            }

            return Content("0");
        }
    }

    public class EntityMetaLinkValuesBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var provider = MetaValuesProviderManager.Provider(controllerContext.HttpContext.Request["MetaValuesProviderName"]);
            if (provider != null)
            {
                return provider.GetSettings(controllerContext);
            }
            return "";
        }
    }
}